package api_services

import (
	"code.gitea.io/gitea/models/db"
	"code.gitea.io/gitea/models/repo"
	DevcontainersVO "code.gitea.io/gitea/routers/api/devcontainer/vo"
	gitea_web_context "code.gitea.io/gitea/services/context"
	DevcontainersService "code.gitea.io/gitea/services/devstar_devcontainer"
	devcontainer_service_errors "code.gitea.io/gitea/services/devstar_devcontainer/errors"
	devcontainer_service_options "code.gitea.io/gitea/services/devstar_devcontainer/options"
	"context"
	"regexp"
)

// CreateDevcontainerAPIService API专用创建 DevContainer Service
func CreateDevcontainerAPIService(ctx *gitea_web_context.Context, opts *devcontainer_service_options.CreateDevcontainerOptions) error {
	// 0. 检查用户传入参数
	if ctx == nil || opts == nil || opts.Actor == nil || opts.RepoId <= 0 {
		return devcontainer_service_errors.ErrIllegalParams{
			FieldNameList: []string{"ctx", "opts", "opts.Actor", "opts.RepoId"},
		}
	}

	// sanitize user-input SSH Public Key List
	regexpInvalidSSHPublicKey := regexp.MustCompile(`[\r]`)
	for _, publicKey := range opts.SSHPublicKeyList {
		if len(publicKey) <= 4 || publicKey[0:4] != "ssh-" || regexpInvalidSSHPublicKey.MatchString(publicKey) {
			// 遇到可能无效的 SSH Public Key，或者导致 k8s Operator YAML 解码失败的字符： `\r`，报错返回
			// ERROR	Reconciler error:
			// {
			//		"controller": "devcontainerapp",
			//		"controllerGroup": "devcontainer.devstar.cn",
			//		"controllerKind": "DevcontainerApp",
			//		"DevcontainerApp": {
			//			"name":      "leviyanx-16-4834a4c88c4511ef9c1a4e1bce2a7080",
			//			"namespace": "devstar-studio-ns"
			//		},
			//		"namespace": "devstar-studio-ns",
			//		"name": "leviyanx-16-4834a4c88c4511ef9c1a4e1bce2a7080",
			//		"reconcileID": "6af51347-7aae-4542-a5cf-2f9b57a202e6",
			//		"error": "panic: error converting YAML to JSON: yaml: line 46: could not find expected ':' [recovered]"
			//	}
			return devcontainer_service_errors.ErrIllegalParams{
				FieldNameList: []string{"SSHPublicKeyList"},
			}
		}
	}

	// 1. 开启事务
	errTxn := db.WithTx(ctx, func(ctx context.Context) error {

		// 1.1 调用 model层，查询数据库，将 repoId 变换为 Repository 对象
		repositoryInDB, err := repo.GetRepositoryByID(ctx, opts.RepoId)
		if err != nil || repositoryInDB == nil {
			return devcontainer_service_errors.ErrIllegalParams{
				FieldNameList: []string{"opts.RepoId"},
			}
		}

		// 1.2 检查该用户在该仓库 是否已经创建过 DevContainer
		optsRepoDevcontainer := &DevcontainersVO.RepoDevcontainerOptions{
			Actor:      opts.Actor,
			Repository: repositoryInDB,
		}
		devcontainerDetails, err := DevcontainersService.GetRepoDevcontainerDetails(ctx, optsRepoDevcontainer)
		if err != nil || devcontainerDetails.DevContainerId > 0 {
			return devcontainer_service_errors.ErrDevcontainerAlreadyCreated{
				Actor:      opts.Actor,
				Repository: repositoryInDB,
			}
		}

		// 1.3 调用 DevContainer Service 创建 DevContainer
		optsCreateDevcontainer := &DevcontainersVO.CreateRepoDevcontainerOptions{
			Actor:            opts.Actor,
			Repository:       repositoryInDB,
			SSHPublicKeyList: opts.SSHPublicKeyList,
		}
		return DevcontainersService.CreateRepoDevcontainer(ctx, optsCreateDevcontainer)
	})

	return errTxn
}
